package com.atldy.commerce.service.impl;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.crypto.digest.MD5;
import cn.hutool.json.JSONUtil;
import com.atldy.commerce.enums.AuthorityConstant;
import com.atldy.commerce.enums.CommonConstant;
import com.atldy.commerce.mapper.EcommerceUserMapper;
import com.atldy.commerce.pojo.EcommerceUser;
import com.atldy.commerce.service.JwtService;
import com.atldy.commerce.vo.LoginUserinfo;
import com.atldy.commerce.vo.UsernameAndPassword;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import io.jsonwebtoken.Jwts;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import sun.misc.BASE64Decoder;

import java.security.KeyFactory;
import java.security.PrivateKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.time.LocalDate;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.temporal.ChronoUnit;
import java.util.Date;

/**
 * @version 1.0
 * @Author: lidongyang
 * @CreateTime: 2021-08-02 20:51
 * @Description：
 */
@Slf4j
@Service
@Transactional(rollbackFor = Exception.class)
public class JwtServiceImpl implements JwtService {

    private final EcommerceUserMapper ecommerceUserMapper;

    public JwtServiceImpl(EcommerceUserMapper ecommerceUserMapper) {
        this.ecommerceUserMapper = ecommerceUserMapper;
    }

    @Override
    public String generatorToken(String username, String password) throws Exception {
        return generatorToken(username, password, 0);
    }

    @Override
    public String generatorToken(String username, String password, int expire) throws Exception {
        //判断用户是否正确
        EcommerceUser user = new EcommerceUser();
        user.setUsername(username);
        user.setPassword(MD5.create().digestHex(password));
        QueryWrapper<EcommerceUser> wrapper = new QueryWrapper<>(user);
        user = ecommerceUserMapper.selectOne(wrapper);
        if (user == null) {
            log.error("查询到用户不存在，用户名：[{}]，密码：[{}]", username, password);
            return null;
        }
        LoginUserinfo userinfo = new LoginUserinfo(user.getId(), user.getUsername());
        //判断token过期时间
        if (expire <= 0) {
            expire = AuthorityConstant.DEFAULT_EXPIRE_DAY;
        }
        //计算token过期时间
        ZonedDateTime zonedDateTime = LocalDate.now()
                .plus(expire, ChronoUnit.DAYS)
                .atStartOfDay(ZoneId.systemDefault());
        Date date = Date.from(zonedDateTime.toInstant());

        //使用jwt生成token
        String token = Jwts.builder()
                .claim(CommonConstant.JWT_TOKEN_USER_INFO, JSONUtil.toJsonStr(userinfo))
                .setId(IdUtil.simpleUUID())
                .setExpiration(date)
                .signWith(privateKey())
                .compact();
        return token;
    }

    @Override
    public String registerAndToken(UsernameAndPassword usernameAndPassword) throws Exception {
        //判断用户是否已经注册
        EcommerceUser user = new EcommerceUser();
        user.setUsername(usernameAndPassword.getUsername());
        QueryWrapper<EcommerceUser> wrapper = new QueryWrapper<>(user);
        user = ecommerceUserMapper.selectOne(wrapper);
        if (user != null) {
            log.error("此用户已存在，用户名：[{}]", user.getUsername());
            return null;
        }
        user = new EcommerceUser();
        user.setUsername(usernameAndPassword.getUsername());
        user.setPassword(MD5.create().digestHex(usernameAndPassword.getPassword()));
        user.setCreateTime(DateUtil.date());
        user.setUpdateTime(DateUtil.date());
        user.setExtraInfo("{}");
        //进行注册
        ecommerceUserMapper.insert(user);
        return generatorToken(usernameAndPassword.getUsername(), usernameAndPassword.getPassword());
    }


    //获取本地私钥
    private PrivateKey privateKey() throws Exception {
        PKCS8EncodedKeySpec keySpec =
                new PKCS8EncodedKeySpec(new BASE64Decoder().decodeBuffer(AuthorityConstant.PRIVATE_KEY));
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        return keyFactory.generatePrivate(keySpec);
    }
}